<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="Node.js, 机会，机遇">
    <meta name="description" content="未来的变数太多，而我所能做的，就是走好这一步。">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>Node.js | 秋去冬来</title>
    <link rel="icon" type="image/png" href="/favicon.png">

    <!-- <link href="https://use.fontawesome.com/releases/v5.0.4/css/all.css" rel="stylesheet"> -->
    <link rel="stylesheet" href="/css/font-awesome.min.css">
    <link rel="stylesheet" href="/css/font-awesome.css">
    
    <link rel="stylesheet" type="text/css" href="/libs/awesome/css/all.css">
    <link rel="stylesheet" type="text/css" href="/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/css/my.css">


    <script src="/libs/jquery/jquery.min.js"></script>



<meta name="generator" content="Hexo 6.1.0"><link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head>




<body>
    
    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/" class="waves-effect waves-light">
                    
                    <img src="/medias/logo.png" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">秋去冬来</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/tags" class="waves-effect waves-light">
      
      <i class="fas fa-tags" style="zoom: 0.6;"></i>
      
      <span>标签</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/categories" class="waves-effect waves-light">
      
      <i class="fas fa-bookmark" style="zoom: 0.6;"></i>
      
      <span>分类</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/archives" class="waves-effect waves-light">
      
      <i class="fas fa-archive" style="zoom: 0.6;"></i>
      
      <span>足迹</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/about" class="waves-effect waves-light">
      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/contact" class="waves-effect waves-light">
      
      <i class="fas fa-comments" style="zoom: 0.6;"></i>
      
      <span>留言板</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/friends" class="waves-effect waves-light">
      
      <i class="fas fa-address-book" style="zoom: 0.6;"></i>
      
      <span>情报处</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <img src="/medias/logo.png" class="logo-img circle responsive-img">
        
        <div class="logo-name">秋去冬来</div>
        <div class="logo-desc">
            
            未来的变数太多，而我所能做的，就是走好这一步。
            
        </div>
    </div>

    

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/tags" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-tags"></i>
			
			标签
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/categories" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-bookmark"></i>
			
			分类
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/archives" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-archive"></i>
			
			归档
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/about" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-user-circle"></i>
			
			关于
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/contact" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-comments"></i>
			
			留言板
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/friends" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-address-book"></i>
			
			友情链接
		</a>
          
        </li>
        
        
    </ul>
</div>


        </div>

        
    </nav>

</header>

    



<div class="bg-cover pd-header post-cover" style="background-image: url('/medias/featureimages/11.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">Node.js</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <link rel="stylesheet" href="/libs/tocbot/tocbot.css">
<style>
    #articleContent h1::before,
    #articleContent h2::before,
    #articleContent h3::before,
    #articleContent h4::before,
    #articleContent h5::before,
    #articleContent h6::before {
        display: block;
        content: " ";
        height: 100px;
        margin-top: -100px;
        visibility: hidden;
    }

    #articleContent :focus {
        outline: none;
    }

    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget {
        width: 345px;
        padding-left: 20px;
    }

    .toc-widget .toc-title {
        padding: 35px 0 15px 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    .toc-widget ol {
        padding: 0;
        list-style: none;
    }

    #toc-content {
        padding-bottom: 30px;
        overflow: auto;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ol li {
        padding-left: 10px;
    }

    #toc-content .toc-link:hover {
        color: #42b983;
        font-weight: 700;
        text-decoration: underline;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
        max-height: 25px;

        position: absolute;
        right: 23.5vw;
        display: block;
    }

    #toc-content .is-active-link {
        color: #42b983;
    }

    #floating-toc-btn {
        position: fixed;
        right: 15px;
        bottom: 76px;
        padding-top: 15px;
        margin-bottom: 0;
        z-index: 998;
    }

    #floating-toc-btn .btn-floating {
        width: 48px;
        height: 48px;
    }

    #floating-toc-btn .btn-floating i {
        line-height: 48px;
        font-size: 1.4rem;
    }
</style>
<div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/tags/JavaScript/">
                                <span class="chip bg-color">JavaScript</span>
                            </a>
                        
                            <a href="/tags/Node/">
                                <span class="chip bg-color">Node</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                    <div class="post-cate">
                        <i class="fas fa-bookmark fa-fw icon-category"></i>
                        
                            <a href="/categories/Node/" class="post-category">
                                Node
                            </a>
                        
                    </div>
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2022-05-04
                </div>
                

                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-check fa-fw"></i>更新日期:&nbsp;&nbsp;
                    2022-05-24
                </div>
                

                
                <div class="info-break-policy">
                    <i class="far fa-file-word fa-fw"></i>文章字数:&nbsp;&nbsp;
                    6.3k
                </div>
                

                
                <div class="info-break-policy">
                    <i class="far fa-clock fa-fw"></i>阅读时长:&nbsp;&nbsp;
                    24 分
                </div>
                

                
                    <div id="busuanzi_container_page_pv" class="info-break-policy">
                        <i class="far fa-eye fa-fw"></i>阅读次数:&nbsp;&nbsp;
                        <span id="busuanzi_value_page_pv"></span>
                    </div>
				
            </div>
        </div>
        <hr class="clearfix">

        

        

        <div class="card-content article-card-content">
            <div id="articleContent">
                <h3 id="1-什么是node"><a href="#1-什么是node" class="headerlink" title="1 什么是node"></a>1 什么是node</h3><p>①	浏览器是 JavaScript 的前端运行环境。</p>
<p>②	Node.js 是 JavaScript 的后端运行环境。</p>
<p>③	Node.js 中无法调用 DOM 和 BOM 等浏览器内置 API。</p>
<h3 id="2-终端中的快捷键"><a href="#2-终端中的快捷键" class="headerlink" title="2 终端中的快捷键"></a>2 终端中的快捷键</h3><p>在 Windows 的 powershell 或 cmd 终端中，我们可以通过如下快捷键，来提高终端的操作效率：</p>
<p>①	使用 ↑ 键，可以快速定位到上一次执行的命令</p>
<p>②	使用 tab 键，能够快速补全路径</p>
<p>③	使用 esc 键，能够快速清空当前已输入的命令</p>
<p>④	输入 cls 命令，可以清空终端</p>
<p>Shift +鼠标右键打开powershell</p>
<h3 id="3-文件操作模块"><a href="#3-文件操作模块" class="headerlink" title="3 文件操作模块"></a>3 文件操作模块</h3><p>如果要在 JavaScript 代码中，使用 fs 模块来操作文件，则需要使用如下的方式先导入它：</p>
<pre class=" language-js"><code class="language-js"><span class="token keyword">const</span> fs<span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span>
</code></pre>
<h4 id="3-1-fs-readFile-的语法格式"><a href="#3-1-fs-readFile-的语法格式" class="headerlink" title="3.1 fs.readFile() 的语法格式"></a>3.1 fs.readFile() 的语法格式</h4><p>使用 fs.readFile() 方法，可以读取指定文件中的内容，语法格式如下：</p>
<pre class=" language-js"><code class="language-js"> fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span>path<span class="token punctuation">[</span><span class="token punctuation">,</span>options<span class="token punctuation">]</span><span class="token punctuation">,</span>callback<span class="token punctuation">)</span>
</code></pre>
<p>参数解读：</p>
<ol>
<li>参数1：必选参数，字符串，表示文件的路径。</li>
<li>参数2：可选参数，表示以什么编码格式来读取文件。</li>
<li>参数3：必选参数，文件读取完成后，通过回调函数拿到读取的结果。</li>
</ol>
<pre class=" language-js"><code class="language-js"><span class="token keyword">const</span> fs<span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">'./file/1.text'</span><span class="token punctuation">,</span><span class="token string">'utf-8'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span>dataStr<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'------'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'dataStr'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
<h4 id="3-2-fs-writeFile-的语法格式"><a href="#3-2-fs-writeFile-的语法格式" class="headerlink" title="3.2  fs.writeFile() 的语法格式"></a>3.2  fs.writeFile() 的语法格式</h4><p>使用 fs.writeFile() 方法，可以向指定的文件中写入内容，语法格式如下：</p>
<pre class=" language-javascript"><code class="language-javascript"> fs<span class="token punctuation">.</span><span class="token function">writerFile</span><span class="token punctuation">(</span>file<span class="token punctuation">,</span>data<span class="token punctuation">[</span><span class="token punctuation">,</span>options<span class="token punctuation">]</span><span class="token punctuation">,</span>callback<span class="token punctuation">)</span>
</code></pre>
<p>参数解读：</p>
<p>	参数1：必选参数，需要指定一个文件路径的字符串，表示文件的存放路径。</p>
<p>	参数2：必选参数，表示要写入的内容。</p>
<p>	参数3：可选参数，表示以什么格式写入文件内容，默认值是 utf8。</p>
<p>	参数4：必选参数，文件写入完成后的回调函数。</p>
<pre class=" language-js"><code class="language-js"><span class="token keyword">const</span> fs<span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">'./file/1.text'</span><span class="token punctuation">,</span><span class="token string">'qdanp'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span>dataStr<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'------'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'dataStr'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
<h3 id="4-path"><a href="#4-path" class="headerlink" title="4 path"></a>4 path</h3><p>path 模块是 Node.js 官方提供的、用来处理路径的模块。它提供了一系列的方法和属性，用来满足用户对路径的处理需求。</p>
<p>例如：</p>
<p>	 path.join() 方法，用来将多个路径片段拼接成一个完整的路径字符串</p>
<p>	 path.basename() 方法，用来从路径字符串中，将文件名解析出来</p>
<p>如果要在 JavaScript 代码中，使用 path 模块来处理路径，则需要使用如下的方式先导入它：</p>
<pre class=" language-js"><code class="language-js"> <span class="token keyword">const</span> path<span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span>
</code></pre>
<h4 id="4-1-path-join-的语法格式"><a href="#4-1-path-join-的语法格式" class="headerlink" title="4.1 path.join() 的语法格式"></a>4.1 path.join() 的语法格式</h4><p>使用 path.join() 方法，可以把多个路径片段拼接为完整的路径字符串，语法格式如下：</p>
<pre class=" language-js"><code class="language-js"> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">.</span><span class="token punctuation">.</span>paths<span class="token punctuation">]</span><span class="token punctuation">)</span>
</code></pre>
<p>参数解读：</p>
<p>	…paths <string> 路径片段的序列</p>
<p>	返回值: <string></p>
<pre class=" language-js"><code class="language-js"> <span class="token keyword">const</span> pathStr<span class="token operator">=</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">'/a'</span><span class="token punctuation">,</span><span class="token string">'/b/c'</span><span class="token punctuation">,</span><span class="token string">'../'</span><span class="token punctuation">,</span><span class="token string">'./d'</span><span class="token punctuation">,</span><span class="token string">'e'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>pathStr<span class="token punctuation">)</span><span class="token comment" spellcheck="true">//输出a/b/d/e</span>
 
 <span class="token keyword">const</span> pathStr2<span class="token operator">=</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span><span class="token string">'./file/1.text'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>pathStr2<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">//输出当前文件所在的目录 \file\1.text</span>
</code></pre>
<p>注意：今后凡是涉及到路径拼接的操作，都要使用 path.join() 方法进行处理。不要直接使用 + 进行字符串的拼接。</p>
<h4 id="4-2-path-basename-的语法格式"><a href="#4-2-path-basename-的语法格式" class="headerlink" title="4.2 path.basename() 的语法格式"></a>4.2 path.basename() 的语法格式</h4><pre class=" language-js"><code class="language-js"> path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>path<span class="token punctuation">[</span><span class="token punctuation">,</span>ext<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>参数解读：</p>
<p>	path <string> 必选参数，表示一个路径的字符串</p>
<p>	ext <string> 可选参数，表示文件扩展名</p>
<p>	返回: <string> 表示路径中的最后一部分</p>
<pre class=" language-js"><code class="language-js"> <span class="token keyword">const</span> fpath<span class="token operator">=</span><span class="token string">'/a/b/c/index.html'</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">//文件存放路径</span>
 
 <span class="token keyword">var</span> fullname<span class="token operator">=</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>fpath<span class="token punctuation">)</span><span class="token punctuation">;</span>
 console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>fullname<span class="token punctuation">)</span><span class="token comment" spellcheck="true">//输出index.html</span>
 
 <span class="token keyword">var</span> nameWithoutExt <span class="token operator">=</span>path<span class="token punctuation">.</span><span class="token function">basename</span><span class="token punctuation">(</span>fpath<span class="token punctuation">,</span><span class="token string">'./html'</span><span class="token punctuation">)</span>
 console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>nameWithoutExt<span class="token punctuation">)</span><span class="token comment" spellcheck="true">//输出index</span>
</code></pre>
<h4 id="4-3-path-extname-的语法格式"><a href="#4-3-path-extname-的语法格式" class="headerlink" title="4.3 path.extname() 的语法格式"></a>4.3 path.extname() 的语法格式</h4><p>使用 path.extname() 方法，可以获取路径中的扩展名部分，语法格式如下：</p>
<pre class=" language-js"><code class="language-js"> path<span class="token punctuation">.</span><span class="token function">extname</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span> 
</code></pre>
<p>参数解读：</p>
<p>	path <string>必选参数，表示一个路径的字符串</p>
<p>	返回: <string> 返回得到的扩展名字符串</p>
<pre class=" language-js"><code class="language-js">  <span class="token keyword">const</span> fpath<span class="token operator">=</span><span class="token string">'/a/b/c/index.html'</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">//文件存放路径</span>
  cosnt fext <span class="token operator">=</span>path<span class="token punctuation">.</span><span class="token function">extname</span><span class="token punctuation">(</span>fpath<span class="token punctuation">)</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>fext<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">//输出.html</span>
</code></pre>
<p>①	fs.writeFile() 方法只能用来创建文件，不能用来创建路径</p>
<p>②	重复调用 fs.writeFile() 写入同一个文件，新写入的内容会覆盖之前的旧内容</p>
<h3 id="5-创建-web-服务器的基本步骤"><a href="#5-创建-web-服务器的基本步骤" class="headerlink" title="5 创建 web 服务器的基本步骤"></a>5 创建 web 服务器的基本步骤</h3><p>①	导入 http 模块</p>
<pre class=" language-js"><code class="language-js"> <span class="token keyword">const</span> http<span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'http'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>②创建 web 服务器实例</p>
<pre class=" language-js"><code class="language-js"> <span class="token keyword">const</span> srever<span class="token operator">=</span>http<span class="token punctuation">.</span><span class="token function">crateServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>③为服务器实例绑定 request 事件，监听客户端的请求</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//使用服务器实例的.on()方法，为服务器绑定一个request事件</span>
 server<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'request'</span><span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     <span class="token comment" spellcheck="true">//只有客户端来请求我们的服务器，就会触发request事件，从而调用这个事件处理函数</span>
     console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Someone visit our web server.'</span><span class="token punctuation">)</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<p>④启动服务器</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//调用server.listen(端口号，cd回调)方法，即可启动web服务器</span>
 server<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'http server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h4 id="5-1-req-请求对象"><a href="#5-1-req-请求对象" class="headerlink" title="5.1 req 请求对象"></a>5.1 req 请求对象</h4><p>只要服务器接收到了客户端的请求，就会调用通过 server.on() 为服务器绑定的 request 事件处理函数。</p>
<p>如果想在事件处理函数中，访问与客户端相关的数据或属性，可以使用如下的方式：</p>
<pre class=" language-js"><code class="language-js"> server<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'request'</span><span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     <span class="token comment" spellcheck="true">//req是请求对象，它包含客户端相关的属性和数据，例如：</span>
    <span class="token comment" spellcheck="true">//req.url是客户端请求的地址</span>
    <span class="token comment" spellcheck="true">//req.method是客户端的请求类型</span>
    cosnt str<span class="token operator">=</span><span class="token template-string"><span class="token string">`Your request url is </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token punctuation">;</span>req<span class="token punctuation">.</span>url<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;,and request method is</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token punctuation">;</span>req<span class="token punctuation">.</span>method<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;`</span></span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h4 id="5-2-res-响应对象"><a href="#5-2-res-响应对象" class="headerlink" title="5.2 res 响应对象"></a>5.2 res 响应对象</h4><p>在服务器的 request 事件处理函数中，如果想访问与服务器相关的数据或属性，可以使用如下的方式：</p>
<pre class=" language-js"><code class="language-js">  server<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'request'</span><span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     <span class="token comment" spellcheck="true">//res是响应对象，它包含客户端相关的属性和数据，例如：</span>
    <span class="token comment" spellcheck="true">//要发送到客户端的字符串</span>
    cosnt str<span class="token operator">=</span><span class="token template-string"><span class="token string">`Your request url is </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token punctuation">;</span>req<span class="token punctuation">.</span>url<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;,and request method is</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token punctuation">;</span>req<span class="token punctuation">.</span>method<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;`</span></span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//res.end()方法的作用</span>
    <span class="token comment" spellcheck="true">//向客户端发送指定的内容，并发结束这次请求处理过程</span>
    res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h4 id="5-3-解决中文乱码问题"><a href="#5-3-解决中文乱码问题" class="headerlink" title="5.3 解决中文乱码问题"></a>5.3 解决中文乱码问题</h4><p>当调用 res.end() 方法，向客户端发送中文内容的时候，会出现乱码问题，此时，需要手动设置内容的编码格式：</p>
<pre class=" language-js"><code class="language-js"> server<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'request'</span><span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     <span class="token comment" spellcheck="true">//发送内容包含中文</span>
     <span class="token keyword">const</span> str<span class="token operator">=</span><span class="token template-string"><span class="token string">`请求URL地址是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token punctuation">;</span>req<span class="token punctuation">.</span>url<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;，请求的地类型是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token punctuation">;</span>req<span class="token punctuation">.</span>method<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;`</span></span><span class="token punctuation">;</span>
     <span class="token comment" spellcheck="true">//为了防止出现中文乱码问题，需要设置响应头Content-Type 的值为text/html;charset=utf-8</span>
     res<span class="token punctuation">.</span><span class="token function">setHeader</span><span class="token punctuation">(</span><span class="token string">'Content-Type'</span><span class="token punctuation">,</span><span class="token string">'text/html;charset=utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token comment" spellcheck="true">//把包含中文的内容，响应给请求头</span>
     res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h4 id="5-4-根据不同的-url-响应不同的-html-内容"><a href="#5-4-根据不同的-url-响应不同的-html-内容" class="headerlink" title="5.4 根据不同的 url 响应不同的 html 内容"></a>5.4 根据不同的 url 响应不同的 html 内容</h4><p>核心实现步骤</p>
<p>①	获取请求的 url 地址</p>
<p>②	设置默认的响应内容为 404 Not found</p>
<p>③	判断用户请求的是否为 &#x2F; 或 &#x2F;index.html 首页</p>
<p>④	判断用户请求的是否为 &#x2F;about.html 关于页面</p>
<p>⑤	设置 Content-Type 响应头，防止中文乱码</p>
<p>⑥	使用 res.end() 把内容响应给客户端</p>
<pre class=" language-js"><code class="language-js"> server<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'request'</span><span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     cosnt url<span class="token operator">=</span>req<span class="token punctuation">.</span>url<span class="token punctuation">;</span>                              <span class="token comment" spellcheck="true">//获取请求的URL地址</span>
     <span class="token keyword">let</span> content<span class="token operator">=</span><span class="token template-string"><span class="token string">`&lt;h1>404 Not found&lt;/h1>`</span></span><span class="token punctuation">;</span>           <span class="token comment" spellcheck="true">//设置默认的响应内容为 404 Not found</span>
     <span class="token keyword">if</span><span class="token punctuation">(</span>url <span class="token operator">===</span><span class="token string">'/'</span> url<span class="token operator">===</span><span class="token string">'/index.html'</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">;</span>
         content<span class="token operator">=</span><span class="token string">'&lt;h1>首页&lt;/h1>'</span><span class="token punctuation">;</span>                    <span class="token comment" spellcheck="true">//用户请求的是首页</span>
     <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token keyword">else</span> <span class="token keyword">if</span><span class="token punctuation">(</span>url<span class="token operator">===</span><span class="token string">'/about.html'</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">;</span>
         constent<span class="token operator">=</span><span class="token string">'&lt;h1>关于&lt;/h1>'</span><span class="token punctuation">;</span>                    <span class="token comment" spellcheck="true">//用户请求的是关于界面</span>
     <span class="token punctuation">}</span><span class="token punctuation">;</span>
     res<span class="token punctuation">.</span><span class="token function">setHeader</span><span class="token punctuation">(</span><span class="token string">'Content-Type'</span><span class="token punctuation">,</span><span class="token string">'text/html;charset=utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">//防止中文乱码</span>
     res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span>constent<span class="token punctuation">)</span><span class="token punctuation">;</span>                                <span class="token comment" spellcheck="true">//把内容发送给客户端</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h3 id="6-什么是模块化"><a href="#6-什么是模块化" class="headerlink" title="6 什么是模块化"></a>6 什么是模块化</h3><p>模块化是指解决一个复杂问题时，自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说，模块是可组合、分解和更换的单元。</p>
<h4 id="6-1-加载模块"><a href="#6-1-加载模块" class="headerlink" title="6.1 加载模块"></a>6.1 加载模块</h4><p>注意：使用 require() 方法加载其它模块时，会执行被加载模块中的代码。</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//加载内置fs模块</span>
 <span class="token keyword">const</span> fs<span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span>
 
 <span class="token comment" spellcheck="true">//加载用户自定义模块</span>
 <span class="token keyword">const</span> custom<span class="token operator">=</span><span class="token function">requir</span><span class="token punctuation">(</span><span class="token string">'./custom.js'</span><span class="token punctuation">)</span>
 
 <span class="token comment" spellcheck="true">//加载第三方模块</span>
 <span class="token keyword">const</span> moment <span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'moment'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<h4 id="6-2-module-exports-对象"><a href="#6-2-module-exports-对象" class="headerlink" title="6.2 module.exports 对象"></a>6.2 module.exports 对象</h4><p>在自定义模块中，可以使用 module.exports 对象，将模块内的成员共享出去，供外界使用。</p>
<p>外界用 require() 方法导入自定义模块时，得到的就是 module.exports 所指向的对象。</p>
<p>使用 require() 方法导入模块时，导入的结果，永远以 module.exports 指向的对象为准。</p>
<h4 id="6-3-exports-对象"><a href="#6-3-exports-对象" class="headerlink" title="6.3 exports 对象"></a>6.3 exports 对象</h4><p>由于 module.exports 单词写起来比较复杂，为了简化向外共享成员的代码，Node 提供了 exports 对象。</p>
<p>默认情况下，exports 和 module.exports 指向同一个对象。</p>
<p>最终共享的结果，还是以 module.exports 指向的对象为准。</p>
<h3 id="7-Node-js-中的模块化规范"><a href="#7-Node-js-中的模块化规范" class="headerlink" title="7 Node.js 中的模块化规范"></a>7 Node.js 中的模块化规范</h3><p>Node.js 遵循了 CommonJS 模块化规范，CommonJS 规定了模块的特性和各模块之间如何相互依赖。</p>
<h4 id="7-1CommonJS-规定："><a href="#7-1CommonJS-规定：" class="headerlink" title="7.1CommonJS 规定："></a>7.1CommonJS 规定：</h4><p>每个模块内部，module 变量代表当前模块。</p>
<p>module 变量是一个对象，它的 exports 属性（即 module.exports）是对外的接口。</p>
<p>加载某个模块，其实是加载该模块的 module.exports 属性。require() 方法用于加载模块。</p>
<p>注意：</p>
<p>	 从 <a target="_blank" rel="noopener" href="https://www.npmjs.com/">https://www.npmjs.com/</a> 网站上搜索自己所需要的包</p>
<p>	 从 <a target="_blank" rel="noopener" href="https://registry.npmjs.org/">https://registry.npmjs.org/</a>  服务器上下载自己需要的包</p>
<h4 id="7-2-快速创建-package-json"><a href="#7-2-快速创建-package-json" class="headerlink" title="7.2 快速创建 package.json"></a>7.2 快速创建 package.json</h4><pre class=" language-js"><code class="language-js"> npm init <span class="token operator">-</span>y
</code></pre>
<p>注意：</p>
<p>①	上述命令只能在英文的目录下成功运行！所以，项目文件夹的名称一定要使用英文命名，不要使用中文，不能出现空格。</p>
<p>②	运行 npm install 命令安装包的时候，npm 包管理工具会自动把包的名称和版本号，记录到 package.json 中。</p>
<p>package.json 文件中，有一个 dependencies 节点，专门用来记录您使用 npm install 命令安装了哪些包。</p>
<p>可以运行 npm install 命令（或 npm i）一次性安装所有的依赖包：</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//执行npm install 命令时，npm包管理工具会先读取package.json中的dependcies节点</span>
 <span class="token comment" spellcheck="true">//读取记录所有依赖包和版本号之后，npm包管路工具会一次性包这些包下载到项目中</span>
 npm install 
</code></pre>
<p>可以运行 npm uninstall 命令，来卸载指定的包：</p>
<h4 id="7-3-devDependencies-节点"><a href="#7-3-devDependencies-节点" class="headerlink" title="7.3 devDependencies 节点"></a>7.3 devDependencies 节点</h4><p>如果某些包只在项目开发阶段会用到，在项目上线之后不会用到，则建议把这些包记录到 devDependencies 节点中。</p>
<p>与之对应的，如果某些包在开发和项目上线之后都需要用到，则建议把这些包记录到 dependencies 节点中。</p>
<p>您可以使用如下的命令，将包记录到 devDependencies 节点中：</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//安装指定包，并记录到devDependencies节点中</span>
 npm i 包名 <span class="token operator">-</span>D
 <span class="token comment" spellcheck="true">//完整写法</span>
 npm install 包名 <span class="token operator">--</span>save<span class="token operator">-</span>dev
</code></pre>
<h4 id="7-4-切换-npm-的下包镜像源"><a href="#7-4-切换-npm-的下包镜像源" class="headerlink" title="7.4 切换 npm 的下包镜像源"></a>7.4 切换 npm 的下包镜像源</h4><pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//查看当前的包镜像源</span>
 npm config <span class="token keyword">get</span> registry
 <span class="token comment" spellcheck="true">//切换下载镜像源</span>
 npm config <span class="token keyword">set</span> registry<span class="token operator">=</span>http<span class="token punctuation">:</span><span class="token operator">/</span><span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token operator">&lt;</span>
 <span class="token comment" spellcheck="true">//检查是否下载成功</span>
 npm config <span class="token keyword">get</span> registry
 
 <span class="token comment" spellcheck="true">//nrm为了更方便的切换下包的镜像源，我们可以安装 nrm 这个小工具，利用 nrm 提供的终端命令，可以快速查看和切换下包的镜像源。</span>
npm i nrm <span class="token operator">-</span>g
<span class="token comment" spellcheck="true">//查看所有可用的镜像源</span>
nrm ls
<span class="token comment" spellcheck="true">//切换镜像源</span>
nrm use taobao
</code></pre>
<h4 id="7-5-i5ting-toc"><a href="#7-5-i5ting-toc" class="headerlink" title="7.5 i5ting_toc"></a>7.5 i5ting_toc</h4><p>i5ting_toc 是一个可以A把 md 文档转为 html 页面的小工具，使用步骤如下：</p>
<pre class=" language-js"><code class="language-js"> npm installl <span class="token operator">-</span>g i5ting_toc
 5ting_toc <span class="token operator">-</span>f 要转换md文件路径<span class="token operator">-</span>o
</code></pre>
<p>内置模块是由 Node.js 官方提供的模块，内置模块的加载优先</p>
<p>使用 require() 加载自定义模块时，必须指定以 .&#x2F; 或 ..&#x2F; 开头的路径标识符。在加载自定义模块时，如果没有指定 .&#x2F; 或 ..&#x2F; 这样的路径标识符，则 node 会把它当作内置模块或第三方模块进行加载。</p>
<p>同时，在使用 require() 导入自定义模块时，如果省略了文件的扩展名，则 Node.js 会按顺序分别尝试加载以下的文件：</p>
<p>①	按照确切的文件名进行加载</p>
<p>②	补全 .js 扩展名进行加载</p>
<p>③	补全 .json 扩展名进行加载</p>
<p>④	补全 .node 扩展名进行加载</p>
<p>⑤	加载失败，终端报错</p>
<h4 id="7-6-第三方模块的加载机制"><a href="#7-6-第三方模块的加载机制" class="headerlink" title="7.6 第三方模块的加载机制"></a>7.6 第三方模块的加载机制</h4><p>如果没有找到对应的第三方模块，则移动到再上一层父目录中，进行加载，直到文件系统的根目录。</p>
<p>当把目录作为模块标识符，传递给 require() 进行加载的时候，有三种加载方式：</p>
<p>在被加载的目录下查找一个叫做 package.json 的文件，并寻找 main 属性，作为 require() 加载的入口</p>
<p>如果目录里没有 package.json 文件，或者 main 入口不存在或无法解析，则 Node.js 将会试图加载目录下的 index.js 文件。</p>
<p>如果以上两步都失败了，则 Node.js 会在终端打印错误消息，报告模块的缺失：Error: Cannot find module ‘xxx’</p>
<h3 id="8-创建基本的-Web-服务器"><a href="#8-创建基本的-Web-服务器" class="headerlink" title="8 创建基本的 Web 服务器"></a>8 创建基本的 Web 服务器</h3><pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//导入express模块</span>
<span class="token keyword">const</span> express<span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//创建web服务器</span>
<span class="token keyword">const</span> app<span class="token operator">=</span><span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment" spellcheck="true">//调用app.listen接口启动服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'http server running at http://127.0.0.1:80'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<p>1 通过 app.get() 方法，可以监听客户端的 GET 请求，具体的语法格式如下：</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//参数1：客户请求的url地址</span>
 <span class="token comment" spellcheck="true">//参数2：请求对应的处理函数</span>
 <span class="token comment" spellcheck="true">//req:请求对象（包含了请求相关的属性和方法）</span>
 <span class="token comment" spellcheck="true">//res:响应对象（包含了响应相关的属性和方法）</span>
 app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'请求url'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">;</span><span class="token regex">/**处理函数/</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<p>2 通过 app.post() 方法，可以监听客户端的 POST 请求，具体的语法格式如下：</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//参数1：客户请求的url地址</span>
 <span class="token comment" spellcheck="true">//参数2：请求对应的处理函数</span>
 <span class="token comment" spellcheck="true">//req:请求对象（包含了请求相关的属性和方法）</span>
 <span class="token comment" spellcheck="true">//res:响应对象（包含了响应相关的属性和方法）</span>
 app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'请求url'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">;</span><span class="token regex">/**处理函数/</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<p>3 通过 res.send() 方法，可以把处理好的内容，发送给客户端：</p>
<pre class=" language-js"><code class="language-js"> app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     <span class="token comment" spellcheck="true">//向客户端发送JSON对象</span>
     res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span>object<span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
     res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'丘东安'</span><span class="token punctuation">)</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<p>4 通过 req.query 对象，可以访问到客户端通过查询字符串的形式，发送到服务器的参数：</p>
<p>注意：默认情况下res.query是一个空对象</p>
<pre class=" language-js"><code class="language-js"> app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     <span class="token comment" spellcheck="true">//客户端使用?name=qda&amp;age=21这种查询字符串的形式，发送到服务器的参数</span>
     <span class="token comment" spellcheck="true">//可以通过req.query对象访问 例如：</span>
     <span class="token comment" spellcheck="true">//req.query.name req.query.age</span>
     console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>query<span class="token punctuation">)</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<p>5 通过 req.params 对象，可以访问到 URL 中，通过 : 匹配到的动态参数：默认是一个空对象</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//url地址中可以听过：参数名 的形式，匹配动态参数值</span>
 app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/user/:id'</span><span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     <span class="token comment" spellcheck="true">//req.parame默认是一个空对象</span>
     <span class="token comment" spellcheck="true">//里面存放通过：动态匹配到的参数值</span>
     console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>params<span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h3 id="9-托管静态资源"><a href="#9-托管静态资源" class="headerlink" title="9 托管静态资源"></a>9 托管静态资源</h3><p>express 提供了一个非常好用的函数，叫做 express.static()，通过它，我们可以非常方便地创建一个静态资源服务器，例如，通过如下代码就可以将 public 目录下的图片、CSS 文件、JavaScript 文件对外开放访问了：</p>
<pre class=" language-js"><code class="language-js"> app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token keyword">static</span><span class="token punctuation">(</span><span class="token string">'public'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre>
<p>注意：Express 在指定的静态目录中查找文件，并对外提供资源的访问路径。</p>
<p>因此，存放静态文件的目录名不会出现在 URL 中。</p>
<p>URL地址拼接时不可以用在&#x2F;前面不可以加. 导入资源时可以.&#x2F;这样写</p>
<h3 id="10-常见的中间件用法："><a href="#10-常见的中间件用法：" class="headerlink" title="10 常见的中间件用法："></a>10 常见的中间件用法：</h3><h4 id="①应用级别的中间件"><a href="#①应用级别的中间件" class="headerlink" title="①应用级别的中间件"></a>①应用级别的中间件</h4><p>通过 app.use() 或 app.get() 或 app.post() ，绑定到 app 实例上的中间件，叫做应用级别的中间件，代码示例如下：</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//全局中间件</span>
 app<span class="token punctuation">.</span><span class="token function">user</span><span class="token punctuation">(</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">,</span>next<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
 <span class="token comment" spellcheck="true">//局部中间件</span>
 app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span>mv1<span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Home page'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h4 id="②-路由级别的中间件"><a href="#②-路由级别的中间件" class="headerlink" title="② 路由级别的中间件"></a>② 路由级别的中间件</h4><p>绑定到 express.Router() 实例上的中间件，叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过，应用级别中间件是绑定到 app 实例上，路由级别中间件绑定到 router 实例上，代码示例如下：</p>
<pre class=" language-js"><code class="language-js"> <span class="token keyword">var</span> express<span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token keyword">var</span> router<span class="token operator">=</span>express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 
 <span class="token comment" spellcheck="true">//路由级别的中间件</span>
 router<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">,</span>next<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
     console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Time'</span><span class="token punctuation">,</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
 app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span>router<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<h4 id="③错误级别的中间件"><a href="#③错误级别的中间件" class="headerlink" title="③错误级别的中间件"></a>③错误级别的中间件</h4><p>错误级别中间件的作用：专门用来捕获整个项目中发生的异常错误，从而防止项目异常崩溃的问题。</p>
<p>格式：错误级别中间件的 function 处理函数中，必须有 4 个形参，形参顺序从前到后，分别是 (err, req, res, next)。</p>
<p>注意：错误级别的中间件，必须注册在所有路由之后！</p>
<pre class=" language-js"><code class="language-js"> app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>                        <span class="token comment" spellcheck="true">//路由</span>
     <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">'服务器内部发生了错误！'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token comment" spellcheck="true">//抛出一个自定义错误</span>
     res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Home page'</span><span class="token punctuation">)</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
 
 app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span>req<span class="token punctuation">,</span>res<span class="token punctuation">,</span>next<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>                    <span class="token comment" spellcheck="true">//错误级别的中间件</span>
     console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'发生了错误'</span><span class="token operator">+</span>err<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token comment" spellcheck="true">//在服务器打印错误信息</span>
     res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'发生了错误'</span><span class="token operator">+</span>err<span class="token punctuation">.</span>message<span class="token punctuation">)</span>            <span class="token comment" spellcheck="true">//向客户端响应错误相关内容</span>
 <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h4 id="④-Express-内置的中间件"><a href="#④-Express-内置的中间件" class="headerlink" title="④	 Express 内置的中间件"></a>④	 Express 内置的中间件</h4><p>自 Express 4.16.0 版本开始，Express 内置了 3 个常用的中间件，极大的提高了 Express 项目的开发效率和体验：</p>
<p> express.static 快速托管静态资源的内置中间件，例如： HTML 文件、图片、CSS 样式等（无兼容性）</p>
<p> express.json 解析 JSON 格式的请求体数据（有兼容性，仅在 4.16.0+ 版本中可用）</p>
<p> express.urlencoded 解析 URL-encoded 格式的请求体数据（有兼容性，仅在 4.16.0+ 版本中可用）</p>
<pre class=" language-js"><code class="language-js"> app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span>extended<span class="token punctuation">:</span>fales<span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre>
<h4 id="⑤-第三方的中间件"><a href="#⑤-第三方的中间件" class="headerlink" title="⑤	 第三方的中间件"></a>⑤	 第三方的中间件</h4><h3 id="10-使用-querystring-模块解析请求体数据"><a href="#10-使用-querystring-模块解析请求体数据" class="headerlink" title="10 使用 querystring 模块解析请求体数据"></a>10 使用 querystring 模块解析请求体数据</h3><p>Node.js 内置了一个 querystring 模块，专门用来处理查询字符串。通过这个模块提供的 parse() 函数，可以轻松把查询字符串，解析成对象的格式。示例代码如下：</p>
<pre class=" language-js"><code class="language-js"> <span class="token keyword">const</span> qs<span class="token operator">=</span><span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'querystring'</span><span class="token punctuation">)</span>
 
 <span class="token keyword">const</span> body<span class="token operator">=</span>qs<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span>
</code></pre>
<p>get通过req.query获得客户端通过查询字符串发送到服务器的数据</p>
<pre class=" language-js"><code class="language-js">    <span class="token keyword">const</span> query <span class="token operator">=</span> req<span class="token punctuation">.</span>query<span class="token punctuation">;</span>
</code></pre>
<p>post通过req.body获取请求体中包含的url-encoded数据</p>
<pre class=" language-js"><code class="language-js"><span class="token keyword">const</span> body <span class="token operator">=</span> req<span class="token punctuation">.</span>body<span class="token punctuation">;</span>
</code></pre>
<p>注意：如果要获取 URL-encoded 格式的请求体数据，必须配置中间件 app.use(express.urlencoded({ extended: false }))</p>
<h3 id="11-跨域问题"><a href="#11-跨域问题" class="headerlink" title="11 跨域问题"></a>11 跨域问题</h3><p>cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件，可以很方便地解决跨域问题。</p>
<p>使用步骤分为如下 3 步：</p>
<p>运行 npm install cors 安装中间件</p>
<pre class=" language-js"><code class="language-js">npm install cors
</code></pre>
<p>使用 const cors &#x3D; require(‘cors’) 导入中间件</p>
<p>在路由之前调用 app.use(cors()) 配置中间件</p>
<p>&#x2F;&#x2F;一定要在路由之前配置cors这个中间件，从而解决接口跨域的问题</p>
<pre class=" language-js"><code class="language-js"><span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>简单请求和预检请求的区别</p>
<p>简单请求的特点：客户端与服务器之间只会发生一次请求。</p>
<p>预检请求的特点：客户端与服务器之间会发生两次请求，OPTION 预检请求成功之后，才会发起真正的请求。</p>
<h3 id="12-MySQL"><a href="#12-MySQL" class="headerlink" title="12 MySQL"></a>12 MySQL</h3><pre class=" language-js"><code class="language-js"><span class="token comment" spellcheck="true">//注意：如果执行的是select查询语句，则执行结果是数组</span>
<span class="token comment" spellcheck="true">//如果执行的是insert into,update,delete语句则results是一个对象，可以通过results.affectRows属性来判断是否插入成功</span>
</code></pre>
<p>注意：千万不要使用 Cookie 存储重要且隐私的数据！比如用户的身份信息、密码等。</p>
<p>注意：</p>
<p>	当前端请求后端接口不存在跨域问题的时候，推荐使用 Session 身份认证机制。</p>
<p>	当前端需要跨域请求后端接口的时候，不推荐使用 Session 身份认证机制，推荐使用 JWT 认证机制。</p>
<h3 id="13-JWT"><a href="#13-JWT" class="headerlink" title="13 JWT"></a>13 JWT</h3><p>JWT总结：用户的信息通过 Token 字符串的形式，保存在客户端浏览器中。服务器通过还原 Token 字符串的形式来认证用户的身份。服务器端不存储</p>
<p>JWT 通常由三部分组成，分别是 Header（头部）、Payload（有效荷载）、Signature（签名）。</p>
<p>三者之间使用英文的“.”分隔，格式如下：</p>
<pre class=" language-js"><code class="language-js"> Header<span class="token punctuation">.</span>Payload<span class="token punctuation">.</span>Signature
</code></pre>
<h5 id="安装-JWT-相关的包"><a href="#安装-JWT-相关的包" class="headerlink" title="安装 JWT 相关的包"></a>安装 JWT 相关的包</h5><ul>
<li>jsonwebtoken 用于生成 JWT 字符串</li>
<li>express-jwt 用于将 JWT 字符串解析还原成 JSON 对象</li>
</ul>
<pre class=" language-js"><code class="language-js">npm install jsonwebtoken express<span class="token operator">-</span>jwt
</code></pre>
<h5 id="导入-JWT-相关的包"><a href="#导入-JWT-相关的包" class="headerlink" title="导入 JWT 相关的包"></a>导入 JWT 相关的包</h5><pre class=" language-js"><code class="language-js"><span class="token comment" spellcheck="true">//1.导入用于生成JWT字符的包</span>
<span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">reqire</span><span class="token punctuation">(</span><span class="token string">'jsonwebtoken'</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true">//2.导入用于客户端发送过来的JWT字符串，解析还原成JSON对象包</span>
<span class="token keyword">const</span> expressJWT <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-jwt'</span><span class="token punctuation">)</span>
</code></pre>
<h5 id="定义-secret-密钥"><a href="#定义-secret-密钥" class="headerlink" title="定义 secret 密钥"></a>定义 secret 密钥</h5><p>为了保证 JWT 字符串的安全性，防止 JWT 字符串在网络传输过程中被别人破解，我们需要专门定义一个用于加密和解密的 secret 密钥：</p>
<p>当生成 JWT 字符串的时候，需要使用 secret 密钥对用户的信息进行加密，最终得到加密好的 JWT 字符串</p>
<p>当把 JWT 字符串解析还原成 JSON 对象的时候，需要使用 secret 密钥进行解密</p>
<pre class=" language-js"><code class="language-js"><span class="token comment" spellcheck="true">//secret 密钥的本质，就是一个字符串</span>
<span class="token keyword">const</span> secretKey <span class="token operator">=</span> <span class="token string">'qqdl_qda'</span>
</code></pre>
<h5 id="在登录成功后生成-JWT-字符串"><a href="#在登录成功后生成-JWT-字符串" class="headerlink" title="在登录成功后生成 JWT 字符串"></a>在登录成功后生成 JWT 字符串</h5><p>调用 jsonwebtoken 包提供的 sign() 方法，将用户的信息加密成 JWT 字符串，响应给客户端：</p>
<pre class=" language-js"><code class="language-js"><span class="token comment" spellcheck="true">//登录接口</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api/login'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//...省略失败的代码</span>
    <span class="token comment" spellcheck="true">//用户登录成功之后，生成JWT字符串，通过token属性响应给客户端</span>
    res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span>
        status<span class="token punctuation">:</span> <span class="token number">200</span><span class="token punctuation">,</span>
        message<span class="token punctuation">:</span> <span class="token string">'登录成功'</span>，
          <span class="token comment" spellcheck="true">//调用jwt.sing()生成JWT字符串，昂参数分贝是：用户信息对象，加密密钥，配置对象</span>
        token<span class="token punctuation">:</span>jwt<span class="token punctuation">.</span><span class="token function">sing</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span>username<span class="token punctuation">:</span> userinfi<span class="token punctuation">.</span>usernaem<span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">,</span>secreKey<span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token punctuation">;</span>expiresIn<span class="token punctuation">:</span><span class="token string">'30s'</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h5 id="将-JWT-字符串还原为-JSON-对象"><a href="#将-JWT-字符串还原为-JSON-对象" class="headerlink" title="将 JWT 字符串还原为 JSON 对象"></a>将 JWT 字符串还原为 JSON 对象</h5><p>客户端每次在访问那些有权限接口的时候，都需要主动通过请求头中的 Authorization 字段，将 Token 字符串发送到服务器进行身份认证。</p>
<p>此时，服务器可以通过 express-jwt 这个中间件，自动将客户端发送过来的 Token 解析还原成 JSON 对象：</p>
<pre class=" language-js"><code class="language-js"><span class="token comment" spellcheck="true">//使用app.use()来注册中间件</span>
<span class="token comment" spellcheck="true">//expressJWT({;secret: secretKey};) 就是用来解析Token的中间件</span>
<span class="token comment" spellcheck="true">// .unless({;path: [/^\/api\//]};) 用来指定哪些接口不需要访问权限</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">expressJWT</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span>secret<span class="token punctuation">:</span> secretKey<span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unless</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span>path<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token operator">/</span><span class="token operator">^</span>\<span class="token operator">/</span>api\<span class="token operator">/</span><span class="token operator">/</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h5 id="使用-req-user-获取用户信息"><a href="#使用-req-user-获取用户信息" class="headerlink" title="使用 req.user 获取用户信息"></a>使用 req.user 获取用户信息</h5><p>当 express-jwt 这个中间件配置成功之后，即可在那些有权限的接口中，使用 req.user 对象，来访问从 JWT 字符串中解析出来的用户信息了，示例代码如下</p>
<pre class=" language-js"><code class="language-js"><span class="token comment" spellcheck="true">//这是一个有权限的接口</span>
app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/admin/getinfo'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span>res<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>user<span class="token punctuation">)</span>
    res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span>
        status<span class="token punctuation">:</span> <span class="token number">200</span><span class="token punctuation">,</span>
        message<span class="token punctuation">:</span> <span class="token string">'获取用户信息成功'</span>
        data<span class="token punctuation">:</span> req<span class="token punctuation">.</span>user
    <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h5 id="捕获解析-JWT-失败后产生的错误"><a href="#捕获解析-JWT-失败后产生的错误" class="headerlink" title="捕获解析 JWT 失败后产生的错误"></a>捕获解析 JWT 失败后产生的错误</h5><p>当使用 express-jwt 解析 Token 字符串时，如果客户端发送过来的 Token 字符串过期或不合法，会产生一个解析失败的错误，影响项目的正常运行。我们可以通过 Express 的错误中间件，捕获这个错误并进行相关的处理，示例代码如下</p>
<pre class=" language-js"><code class="language-js">app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span>req<span class="token punctuation">,</span>res<span class="token punctuation">,</span>next<span class="token punctuation">)</span><span class="token operator">=</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//token解析失败导致的错误</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>err<span class="token punctuation">.</span>name <span class="token operator">===</span> <span class="token string">'UnauthoriZedError'</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span> status<span class="token punctuation">:</span> <span class="token number">401</span><span class="token punctuation">,</span>message<span class="token punctuation">:</span> <span class="token string">'无效token'</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">//其他错误原因导致</span>
    res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span>status<span class="token punctuation">:</span> <span class="token number">500</span><span class="token punctuation">,</span>messgae<span class="token punctuation">:</span> <span class="token string">'未知错误'</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
</code></pre>
<h3 id="14-密码加密"><a href="#14-密码加密" class="headerlink" title="14 密码加密"></a>14 密码加密</h3><p>为了保证密码的安全性，不建议在数据库以 明文 的形式保存用户密码，推荐对密码进行 加密存储</p>
<p>在当前项目中，使用 bcryptjs 对用户密码进行加密，优点： 加密之后的密码，无法被逆向破解 </p>
<p>同一明文密码多次加密，得到的加密结果各不相同，保证了安全性</p>
<pre class=" language-js"><code class="language-js"> <span class="token comment" spellcheck="true">//安装bcryptjs </span>
 npm i bcryptjs 
 
 <span class="token comment" spellcheck="true">//导入bcryptjs </span>
<span class="token keyword">const</span> bcryptjs <span class="token operator">=</span><span class="token function">requies</span><span class="token punctuation">(</span><span class="token string">'bcryptjs '</span><span class="token punctuation">)</span>

<span class="token comment" spellcheck="true">//调用bcryptj.hasnSync(明文密码，随机盐的长度（）)</span>
userinfo<span class="token punctuation">.</span>password<span class="token operator">=</span>bcrypt<span class="token punctuation">.</span><span class="token function">hasnSync</span><span class="token punctuation">(</span>userinfo<span class="token punctuation">.</span>password<span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>  配置解析 Token 的中间件 运行如下的命令，安装解析 Token 的中间件</p>
<pre class=" language-js"><code class="language-js">npm i express<span class="token operator">-</span>jwt@<span class="token number">5.3</span><span class="token punctuation">.</span><span class="token number">3</span>
</code></pre>
<ol>
<li><p>joi.ref(‘oldPwd’) 表示 newPwd 的值必须和 oldPwd 的值保持一致</p>
</li>
<li><p>joi.not(joi.ref(‘oldPwd’)) 表示 newPwd 的值不能等于 oldPwd 的值 </p>
</li>
<li><p>.concat() 用于合并 joi.not(joi.ref(‘oldPwd’)) 和 password 这两条验证规则</p>
</li>
</ol>
<pre class=" language-js"><code class="language-js"> newPwd<span class="token punctuation">:</span> joi<span class="token punctuation">.</span><span class="token function">not</span><span class="token punctuation">(</span>joi<span class="token punctuation">.</span><span class="token function">ref</span><span class="token punctuation">(</span><span class="token string">'oldPwd'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>password<span class="token punctuation">)</span>
</code></pre>
<p> 对密码进行 bcrypt 加密处理 </p>
<pre class=" language-js"><code class="language-js"><span class="token keyword">const</span> Pwd <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">hashSync</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>Pwd<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span>
</code></pre>
<p>Token加密后，数据库密码与用户输入的比较</p>
<pre class=" language-js"><code class="language-js"><span class="token comment" spellcheck="true">// 在头部区域导入 bcryptjs 后， </span>
<span class="token comment" spellcheck="true">// 即可使用 bcrypt.compareSync(提交的密码，数据库中的密码) 方法验证密码是否正确 </span>
<span class="token comment" spellcheck="true">// compareSync() 函数的返回值为布尔值，true 表示密码正确，false 表示密码错误 </span>
<span class="token keyword">const</span> bcrypt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'bcryptjs'</span><span class="token punctuation">)</span> 
<span class="token comment" spellcheck="true">// 判断提交的旧密码是否正确 </span>
<span class="token keyword">const</span> compareResult <span class="token operator">=</span> bcrypt<span class="token punctuation">.</span><span class="token function">compareSync</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">.</span>oldPwd<span class="token punctuation">,</span> results<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>password<span class="token punctuation">)</span> 
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>compareResult<span class="token punctuation">)</span> <span class="token keyword">return</span> res<span class="token punctuation">.</span><span class="token function">cc</span><span class="token punctuation">(</span><span class="token string">'原密码错误！'</span><span class="token punctuation">)</span>
</code></pre>
<p>推荐使用 multer 来解析 multipart&#x2F;form-data 格式的表单数据。</p>
<ol>
<li>运行如下的终端命令，在项目中安装 multer  </li>
<li>模块中导入并配置 multer ：</li>
<li>修改 发布新文章 的路由如下：</li>
</ol>
<pre class=" language-js"><code class="language-js">npm i multer@<span class="token number">1.4</span><span class="token punctuation">.</span><span class="token number">2</span>
<span class="token comment" spellcheck="true">// 导入解析 formdata 格式表单数据的包 </span>
<span class="token keyword">const</span> multer <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'multer'</span><span class="token punctuation">)</span> 
<span class="token comment" spellcheck="true">// 导入处理路径的核心模块 </span>
<span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span> 
<span class="token comment" spellcheck="true">// 创建 multer 的实例对象，通过 dest 属性指定文件的存放路径 </span>
<span class="token keyword">const</span> upload <span class="token operator">=</span> <span class="token function">multer</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">;</span> dest<span class="token punctuation">:</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'../uploads'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true">// 发布新文章的路由 </span>
<span class="token comment" spellcheck="true">// upload.single() 是一个局部生效的中间件，用来解析 FormData 格式的表单数据 </span>
<span class="token comment" spellcheck="true">// 将文件类型的数据，解析并挂载到 req.file 属性中 </span>
<span class="token comment" spellcheck="true">// 将文本类型的数据，解析并挂载到 req.body 属性中s</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/add'</span><span class="token punctuation">,</span> upload<span class="token punctuation">.</span><span class="token function">single</span><span class="token punctuation">(</span><span class="token string">'cover_img'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> article_handler<span class="token punctuation">.</span>addArticle<span class="token punctuation">)</span>
</code></pre>

                
            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="/about" rel="external nofollow noreferrer">qqdl</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="http://example.com/2022/05/04/node/">http://example.com/2022/05/04/node/</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="/about" target="_blank">qqdl</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/tags/JavaScript/">
                                    <span class="chip bg-color">JavaScript</span>
                                </a>
                            
                                <a href="/tags/Node/">
                                    <span class="chip bg-color">Node</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="qq,qzone,wechat,weibo" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
                <style>
    #reward {
        margin: 40px 0;
        text-align: center;
    }

    #reward .reward-link {
        font-size: 1.4rem;
        line-height: 38px;
    }

    #reward .btn-floating:hover {
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2), 0 5px 15px rgba(0, 0, 0, 0.2);
    }

    #rewardModal {
        width: 320px;
        height: 350px;
    }

    #rewardModal .reward-title {
        margin: 15px auto;
        padding-bottom: 5px;
    }

    #rewardModal .modal-content {
        padding: 10px;
    }

    #rewardModal .close {
        position: absolute;
        right: 15px;
        top: 15px;
        color: rgba(0, 0, 0, 0.5);
        font-size: 1.3rem;
        line-height: 20px;
        cursor: pointer;
    }

    #rewardModal .close:hover {
        color: #ef5350;
        transform: scale(1.3);
        -moz-transform:scale(1.3);
        -webkit-transform:scale(1.3);
        -o-transform:scale(1.3);
    }

    #rewardModal .reward-tabs {
        margin: 0 auto;
        width: 210px;
    }

    .reward-tabs .tabs {
        height: 38px;
        margin: 10px auto;
        padding-left: 0;
    }

    .reward-content ul {
        padding-left: 0 !important;
    }

    .reward-tabs .tabs .tab {
        height: 38px;
        line-height: 38px;
    }

    .reward-tabs .tab a {
        color: #fff;
        background-color: #ccc;
    }

    .reward-tabs .tab a:hover {
        background-color: #ccc;
        color: #fff;
    }

    .reward-tabs .wechat-tab .active {
        color: #fff !important;
        background-color: #22AB38 !important;
    }

    .reward-tabs .alipay-tab .active {
        color: #fff !important;
        background-color: #019FE8 !important;
    }

    .reward-tabs .reward-img {
        width: 210px;
        height: 210px;
    }
</style>

<div id="reward">
    <a href="#rewardModal" class="reward-link modal-trigger btn-floating btn-medium waves-effect waves-light red">赏</a>

    <!-- Modal Structure -->
    <div id="rewardModal" class="modal">
        <div class="modal-content">
            <a class="close modal-close"><i class="fas fa-times"></i></a>
            <h4 class="reward-title">你的赏识是我前进的动力</h4>
            <div class="reward-content">
                <div class="reward-tabs">
                    <ul class="tabs row">
                        <li class="tab col s6 alipay-tab waves-effect waves-light"><a href="#alipay">支付宝</a></li>
                        <li class="tab col s6 wechat-tab waves-effect waves-light"><a href="#wechat">微 信</a></li>
                    </ul>
                    <div id="alipay">
                        <img src="/medias/reward/alipay.jpg" class="reward-img" alt="支付宝打赏二维码">
                    </div>
                    <div id="wechat">
                        <img src="/medias/reward/wechat.png" class="reward-img" alt="微信打赏二维码">
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    $(function () {
        $('.tabs').tabs();
    });
</script>

            
        </div>
    </div>

    

    

    

    

    
        <style>
    .valine-card {
        margin: 1.5rem auto;
    }

    .valine-card .card-content {
        padding: 20px 20px 5px 20px;
    }

    #vcomments textarea {
        box-sizing: border-box;
        background: url("/medias/comment_bg.png") 100% 100% no-repeat;
    }

    #vcomments p {
        margin: 2px 2px 10px;
        font-size: 1.05rem;
        line-height: 1.78rem;
    }

    #vcomments blockquote p {
        text-indent: 0.2rem;
    }

    #vcomments a {
        padding: 0 2px;
        color: #4cbf30;
        font-weight: 500;
        text-decoration: none;
    }

    #vcomments img {
        max-width: 100%;
        height: auto;
        cursor: pointer;
    }

    #vcomments ol li {
        list-style-type: decimal;
    }

    #vcomments ol,
    ul {
        display: block;
        padding-left: 2em;
        word-spacing: 0.05rem;
    }

    #vcomments ul li,
    ol li {
        display: list-item;
        line-height: 1.8rem;
        font-size: 1rem;
    }

    #vcomments ul li {
        list-style-type: disc;
    }

    #vcomments ul ul li {
        list-style-type: circle;
    }

    #vcomments table, th, td {
        padding: 12px 13px;
        border: 1px solid #dfe2e5;
    }

    #vcomments table, th, td {
        border: 0;
    }

    table tr:nth-child(2n), thead {
        background-color: #fafafa;
    }

    #vcomments table th {
        background-color: #f2f2f2;
        min-width: 80px;
    }

    #vcomments table td {
        min-width: 80px;
    }

    #vcomments h1 {
        font-size: 1.85rem;
        font-weight: bold;
        line-height: 2.2rem;
    }

    #vcomments h2 {
        font-size: 1.65rem;
        font-weight: bold;
        line-height: 1.9rem;
    }

    #vcomments h3 {
        font-size: 1.45rem;
        font-weight: bold;
        line-height: 1.7rem;
    }

    #vcomments h4 {
        font-size: 1.25rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    #vcomments h5 {
        font-size: 1.1rem;
        font-weight: bold;
        line-height: 1.4rem;
    }

    #vcomments h6 {
        font-size: 1rem;
        line-height: 1.3rem;
    }

    #vcomments p {
        font-size: 1rem;
        line-height: 1.5rem;
    }

    #vcomments hr {
        margin: 12px 0;
        border: 0;
        border-top: 1px solid #ccc;
    }

    #vcomments blockquote {
        margin: 15px 0;
        border-left: 5px solid #42b983;
        padding: 1rem 0.8rem 0.3rem 0.8rem;
        color: #666;
        background-color: rgba(66, 185, 131, .1);
    }

    #vcomments pre {
        font-family: monospace, monospace;
        padding: 1.2em;
        margin: .5em 0;
        background: #272822;
        overflow: auto;
        border-radius: 0.3em;
        tab-size: 4;
    }

    #vcomments code {
        font-family: monospace, monospace;
        padding: 1px 3px;
        font-size: 0.92rem;
        color: #e96900;
        background-color: #f8f8f8;
        border-radius: 2px;
    }

    #vcomments pre code {
        font-family: monospace, monospace;
        padding: 0;
        color: #e8eaf6;
        background-color: #272822;
    }

    #vcomments pre[class*="language-"] {
        padding: 1.2em;
        margin: .5em 0;
    }

    #vcomments code[class*="language-"],
    pre[class*="language-"] {
        color: #e8eaf6;
    }

    #vcomments [type="checkbox"]:not(:checked), [type="checkbox"]:checked {
        position: inherit;
        margin-left: -1.3rem;
        margin-right: 0.4rem;
        margin-top: -1px;
        vertical-align: middle;
        left: unset;
        visibility: visible;
    }

    #vcomments b,
    strong {
        font-weight: bold;
    }

    #vcomments dfn {
        font-style: italic;
    }

    #vcomments small {
        font-size: 85%;
    }

    #vcomments cite {
        font-style: normal;
    }

    #vcomments mark {
        background-color: #fcf8e3;
        padding: .2em;
    }

    #vcomments table, th, td {
        padding: 12px 13px;
        border: 1px solid #dfe2e5;
    }

    table tr:nth-child(2n), thead {
        background-color: #fafafa;
    }

    #vcomments table th {
        background-color: #f2f2f2;
        min-width: 80px;
    }

    #vcomments table td {
        min-width: 80px;
    }

    #vcomments [type="checkbox"]:not(:checked), [type="checkbox"]:checked {
        position: inherit;
        margin-left: -1.3rem;
        margin-right: 0.4rem;
        margin-top: -1px;
        vertical-align: middle;
        left: unset;
        visibility: visible;
    }
</style>

<div class="card valine-card" data-aos="fade-up">
    <div class="comment_headling" style="font-size: 20px; font-weight: 700; position: relative; padding-left: 20px; top: 15px; padding-bottom: 5px;">
        <i class="fas fa-comments fa-fw" aria-hidden="true"></i>
        <span>评论</span>
    </div>
    <div id="vcomments" class="card-content" style="display: grid">
    </div>
</div>

<script src="/libs/valine/av-min.js"></script>
<script src="https://unpkg.com/valine/dist/Valine.min.js"></script>
<script>
    new Valine({
        el: '#vcomments',
        appId: 'nqkOHuiGmn0lIQQD9FcuTyLB-gzGzoHsz',
        appKey: 'E3VTOjSUmjrsA6U340wnUDRz',
        notify: 'false' === 'true',
        verify: 'false' === 'true',
        visitor: 'true' === 'true',
        avatar: 'mm',
        pageSize: '10',
        lang: 'zh-cn',
        placeholder: '评论一下吧',
         enableQQ: true,
        emojiCDN: '//i0.hdslb.com/bfs/emote/',
        // 表情title和图片映射
        emojiMaps: {
            "tv_doge": "6ea59c827c414b4a2955fe79e0f6fd3dcd515e24.png",
            "tv_亲亲": "a8111ad55953ef5e3be3327ef94eb4a39d535d06.png",
            "tv_偷笑": "bb690d4107620f1c15cff29509db529a73aee261.png",
            "tv_再见": "180129b8ea851044ce71caf55cc8ce44bd4a4fc8.png",
            "tv_冷漠": "b9cbc755c2b3ee43be07ca13de84e5b699a3f101.png",
            "tv_发怒": "34ba3cd204d5b05fec70ce08fa9fa0dd612409ff.png",
            "tv_发财": "34db290afd2963723c6eb3c4560667db7253a21a.png",
            "tv_可爱": "9e55fd9b500ac4b96613539f1ce2f9499e314ed9.png",
            "tv_吐血": "09dd16a7aa59b77baa1155d47484409624470c77.png",
            "tv_呆": "fe1179ebaa191569b0d31cecafe7a2cd1c951c9d.png",
            "tv_呕吐": "9f996894a39e282ccf5e66856af49483f81870f3.png",
            "tv_困": "241ee304e44c0af029adceb294399391e4737ef2.png",
            "tv_坏笑": "1f0b87f731a671079842116e0991c91c2c88645a.png",
            "tv_大佬": "093c1e2c490161aca397afc45573c877cdead616.png",
            "tv_大哭": "23269aeb35f99daee28dda129676f6e9ea87934f.png",
            "tv_委屈": "d04dba7b5465779e9755d2ab6f0a897b9b33bb77.png",
            "tv_害羞": "a37683fb5642fa3ddfc7f4e5525fd13e42a2bdb1.png",
            "tv_尴尬": "7cfa62dafc59798a3d3fb262d421eeeff166cfa4.png",
            "tv_微笑": "70dc5c7b56f93eb61bddba11e28fb1d18fddcd4c.png",
            "tv_思考": "90cf159733e558137ed20aa04d09964436f618a1.png",
            "tv_惊吓": "0d15c7e2ee58e935adc6a7193ee042388adc22af.png",
            "tv_打脸": "56ab10b624063e966bfcb76ea5dc4794d87dfd47.png",
            "tv_抓狂": "fe31c08edad661d63762b04e17b8d5ae3c71a757.png",
            "tv_抠鼻": "c666f55e88d471e51bbd9fab9bb308110824a6eb.png",
            "tv_斜眼笑": "911f987aa8bc1bee12d52aafe62bc41ef4474e6c.png",
            "tv_无奈": "ea8ed89ee9878f2fece2dda0ea8a5dbfe21b5751.png",
            "tv_晕": "5443c22b4d07fb1907ccc610c8e6db254f2461b7.png",
            "tv_流汗": "cead1c351ab8d79e9f369605beb90148db0fbed3.png",
            "tv_流泪": "7e71cde7858f0cd50d74b0264aa26db612a8a167.png",
            "tv_流鼻血": "c32d39db2737f89b904ca32700d140a9241b0767.png",
            "tv_点赞": "f85c354995bd99e28fc76c869bfe42ba6438eff4.png",
            "tv_生气": "26702dcafdab5e8225b43ffd23c94ac1ff932654.png",
            "tv_生病": "8b0ec90e6b86771092a498c54f09fc94621c1900.png",
            "tv_疑问": "0793d949b18d7be716078349c202c15ff166f314.png",
            "tv_白眼": "c1d59f439e379ee50eef488bcb5e5378e5044ea4.png",
            "tv_皱眉": "72ccad6679fea0d14cce648b4d818e09b8ffea2d.png",
            "tv_目瞪口呆": "0b8cb81a68de5d5365212c99375e7ace3e7891b7.png",
            "tv_睡着": "8b196675b53af58264f383c50ad0945048290b33.png",
            "tv_笑哭": "1abc628f6d4f4caf9d0e7800878f4697abbc8273.png",
            "tv_腼腆": "89712c0d4af73e67f89e35cbc518420380a7f6f4.png",
            "tv_色": "61822c7e9aae5da76475e7892534545336b23a6f.png",
            "tv_调侃": "4bc022533ef31544ca0d72c12c808cf4a1cce3e3.png",
            "tv_调皮": "b9c41de8e82dd7a8515ae5e3cb63e898bf245186.png",
            "tv_鄙视": "6e72339f346a692a495b123174b49e4e8e781303.png",
            "tv_闭嘴": "c9e990da7f6e93975e25fd8b70e2e290aa4086ef.png",
            "tv_难过": "87f46748d3f142ebc6586ff58860d0e2fc8263ba.png",
            "tv_馋": "fc7e829b845c43c623c8b490ee3602b7f0e76a31.png",
            "tv_鬼脸": "0ffbbddf8a94d124ca2f54b360bbc04feb6bbfea.png",
            "tv_黑人问号": "45821a01f51bc867da9edbaa2e070410819a95b2.png",
            "tv_鼓掌": "1d21793f96ef4e6f48b23e53e3b9e42da833a0f6.png"
        },
        requiredFields: ['nick', 'mail'], //设置必填项
        
    });
</script>

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="fas fa-chevron-left"></i>&nbsp;上一篇</div>
            <div class="card">
                <a href="/2022/05/07/shui-fei/">
                    <div class="card-image">
                        
                        <img src="/medias/featureimages/Water.png" class="responsive-img" alt="饮用水">
                        
                        <span class="card-title">饮用水</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            避免自己忘记什么时候交过
                        
                    </div>
                    <div class="publish-info">
                        <span class="publish-date">
                            <i class="far fa-clock fa-fw icon-date"></i>2022-05-07
                        </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/categories/%E9%A5%AE%E7%94%A8%E6%B0%B4/" class="post-category">
                                    饮用水
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/%E6%B0%B4/">
                        <span class="chip bg-color">水</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/2022/05/04/wen-zhang-shi-li/">
                    <div class="card-image">
                        
                        <img src="/medias/featureimages/book.jpg" class="responsive-img" alt="Front-matter">
                        
                        <span class="card-title">Front-matter</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            Front-matter文章的属性介绍
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2022-05-04
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/categories/Markdown/" class="post-category">
                                    Markdown
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/Typora/">
                        <span class="chip bg-color">Typora</span>
                    </a>
                    
                    <a href="/tags/Markdown/">
                        <span class="chip bg-color">Markdown</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>


<script>
    $('#articleContent').on('copy', function (e) {
        // IE8 or earlier browser is 'undefined'
        if (typeof window.getSelection === 'undefined') return;

        var selection = window.getSelection();
        // if the selection is short let's not annoy our users.
        if (('' + selection).length < Number.parseInt('120')) {
            return;
        }

        // create a div outside of the visible area and fill it with the selected text.
        var bodyElement = document.getElementsByTagName('body')[0];
        var newdiv = document.createElement('div');
        newdiv.style.position = 'absolute';
        newdiv.style.left = '-99999px';
        bodyElement.appendChild(newdiv);
        newdiv.appendChild(selection.getRangeAt(0).cloneContents());

        // we need a <pre> tag workaround.
        // otherwise the text inside "pre" loses all the line breaks!
        if (selection.getRangeAt(0).commonAncestorContainer.nodeName === 'PRE') {
            newdiv.innerHTML = "<pre>" + newdiv.innerHTML + "</pre>";
        }

        var url = document.location.href;
        newdiv.innerHTML += '<br />'
            + '来源: 秋去冬来<br />'
            + '文章作者: 秋去冬来<br />'
            + '文章链接: <a href="' + url + '">' + url + '</a><br />'
            + '本文章著作权归作者所有，任何形式的转载都请注明出处。';

        selection.selectAllChildren(newdiv);
        window.setTimeout(function () {bodyElement.removeChild(newdiv);}, 200);
    });
</script>


<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/libs/codeBlock/codeShrink.js"></script>


    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget card" style="background-color: white;height: 85%;overflow-y: scroll;">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('0'),
            headingSelector: 'h2, h3, h4'
        });

        // modify the toc link href to support Chinese.
        let i = 0;
        let tocHeading = 'toc-heading-';
        $('#toc-content a').each(function () {
            $(this).attr('href', '#' + tocHeading + (++i));
        });

        // modify the heading title id to support Chinese.
        i = 0;
        $('#articleContent').children('h2, h3, h4').each(function () {
            $(this).attr('id', tocHeading + (++i));
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>




    <footer class="page-footer bg-color">
    
    <div class="container row center-align" style="margin-bottom: 0px !important;">
        <div class="col s12 m8 l8 copy-right">
            未来不一定会更好,也可能会更糟
            <br>
            
            
            &nbsp;<i class="fas fa-chart-area"></i>&nbsp;站点总字数:&nbsp;<span
                class="white-color">31.4k</span>&nbsp;字
            
            
            
            
            
            
            <span id="busuanzi_container_site_pv">
                |&nbsp;<i class="far fa-eye"></i>&nbsp;总访问量:&nbsp;<span id="busuanzi_value_site_pv"
                    class="white-color"></span>&nbsp;次
            </span>
            
            
            <span id="busuanzi_container_site_uv">
                |&nbsp;<i class="fas fa-users"></i>&nbsp;总访问人数:&nbsp;<span id="busuanzi_value_site_uv"
                    class="white-color"></span>&nbsp;人
            </span>
            
            <br>
            
            <br>
            
        </div>
        <div class="col s12 m4 l4 social-link social-statis">
    <a href="https://gitee.com/autumn-goes-and-winter-comes" class="tooltipped" target="_blank" data-tooltip="访问我的GitHub" data-position="top" data-delay="50">
        <i class="fab fa-github"></i>
    </a>









    <a href="tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=2817331171" class="tooltipped" target="_blank" data-tooltip="QQ联系我: 2817331171" data-position="top" data-delay="50">
        <i class="fab fa-qq"></i>
    </a>







</div>
    </div>
</footer>

<div class="progress-bar"></div>

    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script type="text/javascript">
$(function () {
    var searchFunc = function (path, search_id, content_id) {
        'use strict';
        $.ajax({
            url: path,
            dataType: "xml",
            success: function (xmlResponse) {
                // get the contents from search data
                var datas = $("entry", xmlResponse).map(function () {
                    return {
                        title: $("title", this).text(),
                        content: $("content", this).text(),
                        url: $("url", this).text()
                    };
                }).get();
                var $input = document.getElementById(search_id);
                var $resultContent = document.getElementById(content_id);
                $input.addEventListener('input', function () {
                    var str = '<ul class=\"search-result-list\">';
                    var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                    $resultContent.innerHTML = "";
                    if (this.value.trim().length <= 0) {
                        return;
                    }
                    // perform local searching
                    datas.forEach(function (data) {
                        var isMatch = true;
                        var data_title = data.title.trim().toLowerCase();
                        var data_content = data.content.trim().replace(/<[^>]+>/g, "").toLowerCase();
                        var data_url = data.url;
                        data_url = data_url.indexOf('/') === 0 ? data.url : '/' + data_url;
                        var index_title = -1;
                        var index_content = -1;
                        var first_occur = -1;
                        // only match artiles with not empty titles and contents
                        if (data_title !== '' && data_content !== '') {
                            keywords.forEach(function (keyword, i) {
                                index_title = data_title.indexOf(keyword);
                                index_content = data_content.indexOf(keyword);
                                if (index_title < 0 && index_content < 0) {
                                    isMatch = false;
                                } else {
                                    if (index_content < 0) {
                                        index_content = 0;
                                    }
                                    if (i === 0) {
                                        first_occur = index_content;
                                    }
                                }
                            });
                        }
                        // show search results
                        if (isMatch) {
                            str += "<li><a href='" + data_url + "' class='search-result-title'>" + data_title + "</a>";
                            var content = data.content.trim().replace(/<[^>]+>/g, "");
                            if (first_occur >= 0) {
                                // cut out 100 characters
                                var start = first_occur - 20;
                                var end = first_occur + 80;
                                if (start < 0) {
                                    start = 0;
                                }
                                if (start === 0) {
                                    end = 100;
                                }
                                if (end > content.length) {
                                    end = content.length;
                                }
                                var match_content = content.substr(start, end);
                                // highlight all keywords
                                keywords.forEach(function (keyword) {
                                    var regS = new RegExp(keyword, "gi");
                                    match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
                                });

                                str += "<p class=\"search-result\">" + match_content + "...</p>"
                            }
                            str += "</li>";
                        }
                    });
                    str += "</ul>";
                    $resultContent.innerHTML = str;
                });
            }
        });
    };

    searchFunc('/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/libs/materialize/materialize.min.js"></script>
    <script src="/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/libs/aos/aos.js"></script>
    <script src="/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/js/matery.js"></script>

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/libs/others/clicklove.js" async="async"></script>
    
    
    <script async src="/libs/others/busuanzi.pure.mini.js"></script>
    

    

    

	
    

    

    

    
    <script src="/libs/instantpage/instantpage.js" type="module"></script>
    
    <script src="/js/snow.js"></script>
    <script src="/js/cursor.js"></script>
<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"/live2dw/assets/haruto.model.json"},"display":{"position":"left","width":150,"height":300,"top":"-20px","right":"-20px"},"mobile":{"show":false},"react":{"opacity":0.7},"log":false});</script></body>

</html>
